// 父类：公共属性和方法
function Person(name, age, friends) {
  this.name = name
  this.age = age
  this.friends = friends
}

Person.prototype.eating = function() {
  console.log(this.name + " eating")
}

// 子类：特有属性和方法
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends)
  this.sno = sno
}

Student.prototype = new Person() // Student 的显示原型 prototype 指向 Person 类的对象

Student.prototype.studying = function() {
  console.log(this.name + " studying")
}

var stu = new Student('why', 18, ['jelly'], 07)
console.log(stu.name) // why
stu.eating() // why eating

// 通过借用构造函数方案能解决原型链的三个弊端

// 原型链实现继承的弊端：
// 1. 打印 stu 对象，继承的属性是看不到的
console.log(stu) // 无 name 属性

// 2. 创建出来两个 stu 对象
var stu1 = new Student('jelly', 23, ['cason'], 14)
var stu2 = new Student('cason', 22, ['jelly'], 07)

// 直接修改对象上的属性，是给本对象添加了一个新属性
stu1.name = "kobe"
console.log(stu2.name) // why

// 获取引用，修改里面的值，会相互影响
stu1.friends.push("kobe")

console.log(stu1.friends) // ['kobe']
console.log(stu2.friends) // ['kobe']

// 3. 在例子实现类的过程中都没有传递参数

// 强调：借用构造函数也是有弊端的：
// 1. Person 函数至少被调用了两次
// 2. stu 的原型对象上会多出一些属性，这些属性是没必要存在的 (第18行代码)